package com.user.mediacoderdemo;

import android.media.MediaCodec;
import android.media.MediaExtractor;
import android.media.MediaFormat;
import android.util.Log;

import java.nio.ByteBuffer;
import java.util.Timer;
import java.util.TimerTask;


/**
 * Created by zoudong on 2017/2/11.
 */

public class WorkDecoder implements  Runnable{
     static final String TAG = "WorkDecoder";
    private final AbsMediaCodecWraper mDecoder;
    private Thread encoderThread;
    boolean isloop;
    private MediaExtractor mMediaExtractor;
    private boolean isRun=false;
    private boolean isPause=false;
    private  Timer inputTimer,outputTimer;
    private  long  curr_percent;
    private final MediaFormat trackFormat;

    public WorkDecoder(AbsMediaCodecWraper codec,MediaExtractor mediaExtractor, boolean isloop) { //是否循环
        this.isloop = isloop;
        this.mDecoder =codec;
        inputTimer = new Timer("input",true);
        this.mMediaExtractor = mediaExtractor;
        trackFormat = mediaExtractor.getTrackFormat(mediaExtractor.getSampleTrackIndex());
        if (mMediaExtractor == null) {
            throw new NullPointerException("mediaExtractor= null");
        }
        if (mDecoder == null) {
            throw new NullPointerException("codec= null");
        }
    }

    @Override
    public void run() {
        boolean isEOS=false;
        while (isRun&&!Thread.currentThread().isInterrupted()) {
            if (!isEOS) {
                int index = mDecoder.dequeueInputBuffer(0);//eos时  不能dequeueInputBuffer
//                Log.d(TAG,"index="+index);   //如果只 dequeueInputBuffer  不 dequeueOutputBuffer   input 会阻塞
                if (index >= 0) {
                    ByteBuffer buffer = mDecoder.getInputBuffer(index);
                    if (buffer==null) break;
                    int sampleSize = mMediaExtractor.readSampleData(buffer, 0);
                    if (sampleSize < 0) {
                        mDecoder.setOnBufferingUpdateListener(1);
                        Log.d(TAG,"Input buffer eos");
//                        isEOS = true;
                        mDecoder.queueInputBuffer(index, 0, 0, 0, MediaCodec.BUFFER_FLAG_END_OF_STREAM);
                    } else {
                        curr_percent+=sampleSize;
                        Log.d(TAG,"----time" + mMediaExtractor.getSampleTime());
                        Log.d(TAG,"----size" + curr_percent);
                        mDecoder.setOnBufferingUpdateListener(-1);
                        mDecoder.queueInputBuffer(index, 0, sampleSize, 0, 0);
                        mMediaExtractor.advance();
                    }
                }
            }

        }
    }
    private class OutputTask extends TimerTask {
        private  boolean format_changed=false;
        private MediaFormat outputFormat;

        @Override
        public void run() {
            if (!isPause) {
                MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
                int outindex = mDecoder.dequeueOutputBuffer(info,-1);
                //  outindex<0 时   mDecoder.releaseOutputBuffer(outindex, false);  出现异常 ->android.media.MediaCodec$CodecException: Error 0xffffffde
                if (outindex >= 0) {
                    if (BuildConfig.DEBUG)
                        Log.d(TAG, "info.presentationTimeUs:" + info.presentationTimeUs);
                    if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
                        Log.d(TAG, "OutputBuffer BUFFER_FLAG_END_OF_STREAM");
                        isPause = true;
                        mDecoder.setOnCompletionListener();
                    } else {
                        mDecoder.setOnPlayeringUpdateListener(info.presentationTimeUs,trackFormat.getLong(MediaFormat.KEY_DURATION));
                        mDecoder.releaseOutputBuffer(outindex, true);
                    }
                }else if (outindex == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
                    Log.d(TAG, "INFO_OUTPUT_BUFFERS_CHANGED");
                } else if (outindex == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
                    format_changed=true;
                    outputFormat = mDecoder.getOutputFormat();
                    Log.e("zoudong", ": "+outputFormat.toString());
                    Log.d(TAG, "New format " + outputFormat);
                } else if (outindex == MediaCodec.INFO_TRY_AGAIN_LATER) {
                    Log.d(TAG, "dequeueOutputBuffer timed out!");
                }else if (outindex<-3){

               }
            }
        }
    }
    public void  start(){

        if (!isRuning()) {
            stop();
            isRun=true;
            encoderThread = new Thread(this, "decoderThread");
            encoderThread.start();
        }
        isPause=false;

        if (outputTimer==null) {
            outputTimer = new Timer("output",true);
            outputTimer.schedule(new OutputTask(), 33, 33);
        }

    }
    public  void stop(){
            isRun=false;
        if (outputTimer != null) {
            outputTimer.cancel();
            outputTimer=null;
        }
        if (encoderThread!=null&&!encoderThread.isInterrupted()) {
            encoderThread.interrupt();
            encoderThread=null;
        }
    }

    public boolean isRuning() {
        return isRun&&!isPause;
    }

    public void pause() {
        isPause=true;
        if (outputTimer != null) {
            outputTimer.cancel();
            outputTimer=null;
        }
        Log.e("zoudong", ": ");
//        try {
//            encoderThread.join();
//        } catch (InterruptedException e) {
//            e.printStackTrace();
//        }
    }
}
